package com.qishi.ex3.connector.http;

import com.qishi.ex3.connector.RequestStream;
import org.apache.catalina.util.ParameterMap;
import org.apache.catalina.util.RequestUtil;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.Socket;
import java.security.Principal;
import java.text.SimpleDateFormat;
import java.util.*;

public class HttpRequest implements HttpServletRequest{

    private String contentType;
    private int contentLength;
    private InetAddress inetAddress;
    private InputStream input;
    private String method;
    private String protocol;
    private String queryString;
    private String requestURI;
    private String serverName;
    private int serverPort;
    private Socket socket;
    private boolean requestedSessionCookie;
    private String requestedSessionId;
    private boolean requestedSessionURL;

    /**
     * 请求的属性
     */
    protected HashMap attributes = new HashMap();

    /**
     * 请求的授权凭证
     */
    protected String authorization = null;

    /**
     * 请求的上下文路径
     */
    protected String contextPath = "";

    /**
     *  请求里的cookie集合
     */
    protected ArrayList cookies = new ArrayList();

    /**
     * 用于返回空枚举的空集合。不添加任何元素到这个集合
     */
    protected static ArrayList empty = new ArrayList();

    /**
     * 在 getDateHeader()中使用的simpleDateFormat集合
     */
    protected SimpleDateFormat formats[] = {
            new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.CHINA),
            new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz",Locale.CHINA),
            new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy",Locale.CHINA)
    };

    /**
     * http请求里的请求头 是键值对模式
     */
    protected HashMap headers = new HashMap();

    protected ParameterMap parameters = null;

    /**
     * 是否已经解析过该请求的参数
     */
    protected boolean parsed = false;
    protected String pathInfo = null;

    protected BufferedReader reader = null;

    protected ServletInputStream stream = null;

    public HttpRequest(InputStream input) {
        this.input = input;
    }


    public void addHeader(String name, String value) {
        name = name.toLowerCase();
        synchronized (headers) {
            ArrayList values = (ArrayList) headers.get(name);
            if(values == null) {
                values = new ArrayList();
                headers.put(name,values);
            }
            values.add(value);
        }
    }

    /**
     * 解析此请求的参数，如果尚未发生。如果在查询字符串和请求中都存在参数内容，它们被合并。
     */
    protected void parseParameters() {
        if(parsed) {
            return;
        }
        ParameterMap results = parameters;
        if(results == null) {
            results = new ParameterMap();
        }
        results.setLocked(false);//打开锁 使其可写
        String encoding = getCharacterEncoding();
        if(encoding == null) {
            encoding = "ISO-8859-1";
        }

        //解析查询字符串中指定的任何参数
        String queryString = getQueryString();
        RequestUtil.parseParameters(results,queryString,encoding);

        //解析输入流中指定的任何参数
        String contentType = getContentType();
        if(contentType == null) {
            contentType = "";
        }
        int semicolon = contentType.indexOf(";");
        if(semicolon >= 0) {
            contentType = contentType.substring(0,semicolon).trim();
        }else {
            contentType = contentType.trim();
        }

        if ("POST".equals(getMethod()) && (getContentLength() > 0)
                && "application/x-www-form-urlencoded".equals(contentType)) {

            try {
                int max = getContentLength();
                int len = 0;
                byte[] buf = new byte[getContentLength()];
                ServletInputStream is = getInputStream();
                while(len<max) {
                    int next = is.read(buf,len,max-len);
                    if(next < 0) {
                        break;
                    }
                    len += next;
                }
                is.close();
                if(len < max) {
                    throw new RuntimeException("content length mismatch");
                }
                RequestUtil.parseParameters(results,buf,encoding);
            }catch (UnsupportedEncodingException e) {

            }catch (IOException e) {
                throw new RuntimeException("content read fail");
            }
        }
        //
        results.setLocked(true);
        parsed = true;
        parameters = results;

    }

    public void addCookie(Cookie cookie){
        synchronized (cookies) {
            cookies.add(cookie);
        }
    }

    public ServletInputStream createInputStream() throws IOException {
        return (new RequestStream());
    }

    public InputStream getStream() {
        return input;
    }

    //TODO 未完待续





    public String getAuthType() {
        return null;
    }

    public Cookie[] getCookies() {
        return new Cookie[0];
    }

    public long getDateHeader(String s) {
        return 0;
    }

    public String getHeader(String s) {
        return null;
    }

    public Enumeration getHeaders(String s) {
        return null;
    }

    public Enumeration getHeaderNames() {
        return null;
    }

    public int getIntHeader(String s) {
        return 0;
    }

    public String getMethod() {
        return null;
    }

    public String getPathInfo() {
        return null;
    }

    public String getPathTranslated() {
        return null;
    }

    public String getContextPath() {
        return null;
    }

    public String getQueryString() {
        return null;
    }

    public String getRemoteUser() {
        return null;
    }

    public boolean isUserInRole(String s) {
        return false;
    }

    public Principal getUserPrincipal() {
        return null;
    }

    public String getRequestedSessionId() {
        return null;
    }

    public String getRequestURI() {
        return null;
    }

    public StringBuffer getRequestURL() {
        return null;
    }

    public String getServletPath() {
        return null;
    }

    public HttpSession getSession(boolean b) {
        return null;
    }

    public HttpSession getSession() {
        return null;
    }

    public boolean isRequestedSessionIdValid() {
        return false;
    }

    public boolean isRequestedSessionIdFromCookie() {
        return false;
    }

    public boolean isRequestedSessionIdFromURL() {
        return false;
    }

    public boolean isRequestedSessionIdFromUrl() {
        return false;
    }

    public Object getAttribute(String s) {
        return null;
    }

    public Enumeration getAttributeNames() {
        return null;
    }

    public String getCharacterEncoding() {
        return null;
    }

    public void setCharacterEncoding(String s) throws UnsupportedEncodingException {

    }

    public int getContentLength() {
        return 0;
    }

    public String getContentType() {
        return null;
    }

    public ServletInputStream getInputStream() throws IOException {
        return null;
    }

    public String getParameter(String s) {
        return null;
    }

    public Enumeration getParameterNames() {
        return null;
    }

    public String[] getParameterValues(String s) {
        return new String[0];
    }

    public Map getParameterMap() {
        return null;
    }

    public String getProtocol() {
        return null;
    }

    public String getScheme() {
        return null;
    }

    public String getServerName() {
        return null;
    }

    public int getServerPort() {
        return 0;
    }

    public BufferedReader getReader() throws IOException {
        return null;
    }

    public String getRemoteAddr() {
        return null;
    }

    public String getRemoteHost() {
        return null;
    }

    public void setAttribute(String s, Object o) {

    }

    public void removeAttribute(String s) {

    }

    public Locale getLocale() {
        return null;
    }

    public Enumeration getLocales() {
        return null;
    }

    public boolean isSecure() {
        return false;
    }

    public RequestDispatcher getRequestDispatcher(String s) {
        return null;
    }

    public String getRealPath(String s) {
        return null;
    }

    public int getRemotePort() {
        return 0;
    }

    public String getLocalName() {
        return null;
    }

    public String getLocalAddr() {
        return null;
    }

    public int getLocalPort() {
        return 0;
    }
}
